<?php
    class charts_model extends Model
    {
        //no database usage model
        private $xml = null;
        private $ready = false;
        private $caption;
        private $subCaption;
        private $showBorder;
        private $showValues;
        private $showPercentValues;
        private $formatNumberScale;
        private $xaxisName;
        private $yaxisName;
        private $pieSliceDepth;
        private $numberPrefix;
        private $dataSet;
        private $category;
        const XML_BASE = '<chart %s>%s</chart>';
        const XML_ATTRIBUTE = " %s='%s' ";
        const XML_SELF_CLOSE = "<%s %s />";
        const XML_OPEN = "<%s %s >%s</%s>";

        public function __construct(){
            parent::__construct();
            //need library FusionCharts
            $this->load->library('FusionCharts');
            $this->clear();
        }

        public function setCaption($value){
            $this->disableExport();
            $this->caption = htmlspecialchars(strval($value));
        }

        public function setSubCaption($value){
            $this->disableExport();
            $this->subCaption = htmlspecialchars(strval($value));
        }

        public function setShowBorder($value){
            $this->disableExport();
            $this->showBorder = !$value ? '0' : '1';
        }

        public function setShowValues($value){
            $this->disableExport();
            $this->showValues = !$value ? '0' : '1';
        }

        public function setFormatNumberScale($value){
            $this->disableExport();
            $this->formatNumberScale = !$value ? '0' : '1';
        }
        
        public function setAxisName($direction, $value){
            $this->disableExport();
            $direction = strtolower($direction);
            if (0 !== strcasecmp($direction, 'x') && 0 !== strcasecmp($direction, 'y')) return;
            $this->{"${direction}axisName"} = htmlspecialchars(strval($value));
        }

        public function setPieSliceDepth($value){
            $this->disableExport();
            $this->pieSliceDepth = strval(intval($value));
        }

        public function setShowPercentValues($value){
            $this->disableExport();
            $this->showPercentValues = !$value ? '0' : '1';
        }

        public function setNumberPrefix($value){
            $this->disableExport();
            $this->numberPrefix = htmlspecialchars(strval($value));
        }

        public function exportXML(){
            if ($this->ready || null != $this->xml){
                //ready to export
                if (null == $this->xml) $this->buildXML();
                $this->clear();
                return $this->xml;
            }
            return null;
        }

        public function renderCharts($chartNames, $divIds, $x, $y, $debugMode = false, 
            $registWithJS = false , $transparent = false){
            $this->exportXML();
            if ($this->ready || null != $this->xml){
                if (!is_array($chartNames)) $chartNames = array($chartNames);
                if (!is_array($divIds)) $divIds = array($divIds);
                $code = array();
                foreach($chartNames as $key => $name){
                    if (!in_array($name, getChartsInfo())) continue;
                    $code[$key] = renderChart(SYS_CHARTS_SWF . "/${name}.swf", '', $this->xml, 
                        htmlspecialchars(strval($divIds[$key])), $x, $y, $debugMode, $registWithJS, $transparent);
                }
                return $code;
            }
            return null;
        }

        public function clear(){
            $this->caption = null;
            $this->subCaption = null;
            $this->showBorder = null;
            $this->showValues = null;
            $this->formatNumberScale = null;
            $this->xaxisName = null;
            $this->yaxisName = null;
            $this->pieSliceDepth = null;
            $this->percentValue = null;
            $this->numberPrefix = null;
        }

        public function setCategory($categories){
            if (null == $categories) $this->category = null;
            if (!is_array($categories)) $categories = array($categories);
            if (empty($categories)) return;
            array_walk($categories, create_function('&$item, $key', '$item = htmlspecialchars(strval($item));'));
            $this->category = $this->buildCategories($categories);
        }

        public function setDataSet($dataSet){
            $this->ready = true;
            if (!is_array($dataSet)) return;
            if (empty($dataSet)) return;
            $this->dataSet = $this->buildDataSets($dataSet, 1 == count($dataSet));
        }

        private function buildXML(){
            $attr = '';
            $attr .= $this->buildAttr('caption', $this->caption);
            $attr .= $this->buildAttr('subCaption', $this->subCaption);
            $attr .= $this->buildAttr('showBorder', $this->showBorder);
            $attr .= $this->buildAttr('showValues', $this->showValues);
            $attr .= $this->buildAttr('formatNumberScale', $this->formatNumberScale);
            $attr .= $this->buildAttr('xAxisName', $this->xaxisName);
            $attr .= $this->buildAttr('yAxisName', $this->yaxisName);
            $attr .= $this->buildAttr('pieSliceDepth', $this->pieSliceDepth);
            $attr .= $this->buildAttr('percentValue', $this->percentValue);
            $attr .= $this->buildAttr('numberPrefix', $this->numberPrefix);
            $this->xml = sprintf(self::XML_BASE, $attr, $this->category . $this->dataSet);
        }

        private function buildCategories($categories){
            $info = '';
            foreach($categories as $value){
                $info .= sprintf(self::XML_SELF_CLOSE, 'category',
                    sprintf(self::XML_ATTRIBUTE, 'name', strval($value)));
            }
            return sprintf(self::XML_OPEN, 'categories', '', $info, 'categories');
        }

        private function buildDataSets($datasets, $raw = false){
            if ($raw){
                //single info output
                $info = '';
                foreach($datasets[0] as $value){
                    $info .= sprintf(self::XML_SELF_CLOSE, 'set',
                        sprintf(self::XML_ATTRIBUTE, 'label', strval($value['name'])) .
                        sprintf(self::XML_ATTRIBUTE, 'value', strval(floatval($value['value']))));
                }
                return $info;
            }
            else{
                //multi info output
                $dataset = '';
                foreach($datasets as $key => &$value){
                    $set = '';
                    foreach($value as $eachSet){
                        $set .= sprintf(self::XML_SELF_CLOSE, 'set',
                            sprintf(self::XML_ATTRIBUTE, 'value', strval(floatval($value['value']))));
                    }
                    $dataset .= sprintf(self::XML_OPEN, 'dataset', 
                        sprintf(self::XML_ATTRIBUTE, 'seriesName', strval($key)), $set, 'dataset');
                }
                return $dataset;
            }
        }

        private function buildAttr($name, $val){
            return null != $val ? sprintf(self::XML_ATTRIBUTE, $name, $val) : '';
        }

        private function disableExport(){
            $this->ready = false;
            $this->xml = null;
        }
    }